package com.hmall.search.service.impl;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hmall.feign.client.ItemClient;
import com.hmall.feign.domain.dto.ItemDTO;
import com.hmall.feign.domain.dto.PageDTO;
import com.hmall.search.domain.po.ItemDoc;
import com.hmall.search.domain.query.ItemPageQuery;
import com.hmall.search.service.SearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class SearchServiceImpl implements SearchService {
    RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(HttpHost.create("http://192.168.154.150:9200")));

    /**
     * 过滤项聚合功能
     * @param itemPageQuery
     * @return
     */
    @Override
    public Map<String, List<String>> filters(ItemPageQuery itemPageQuery) {
        try {
            //请求
            SearchRequest request = new SearchRequest("hmall");
            //参数
            request.source().size(0);
            request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(20));
            request.source().aggregation(AggregationBuilders.terms("categoryAgg").field("category").size(20));
            //发送请求
            SearchResponse response = client.search(request,RequestOptions.DEFAULT);
            //解析结果
            HashMap<String, List<String>> map = parseResult(response);
            return map;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    //解析聚合结果
    private HashMap<String, List<String>> parseResult(SearchResponse response) {
        HashMap<String, List<String>> map = new HashMap<>();
        //品牌
        Terms brandAgg = response.getAggregations().get("brandAgg");
        ArrayList<String> brandList = new ArrayList<>();
        for (Terms.Bucket bucket : brandAgg.getBuckets()) {
            String key = bucket.getKeyAsString();
            brandList.add(key);
        }
        map.put("brand",brandList);
        //分类
        Terms categoryAgg = response.getAggregations().get("categoryAgg");
        ArrayList<String> categoryList = new ArrayList<>();
        for (Terms.Bucket bucket : categoryAgg.getBuckets()) {
            String key = bucket.getKeyAsString();
            categoryList.add(key);
        }
        map.put("category",categoryList);
        return map;
    }

    /**
     * 基本搜索功能
     * @param itemPageQuery
     * @return
     */
    @Override
    public PageDTO<ItemDoc> search(ItemPageQuery itemPageQuery) {
        try {
            //请求
            SearchRequest request = new SearchRequest("hmall");
            //复合查询参数
            BoolQueryBuilder bool = boolSearch(itemPageQuery);
            request.source().query(bool);
            //排序
            if (!itemPageQuery.getSortBy().equals("default")){
                request.source().sort(itemPageQuery.getSortBy(), SortOrder.DESC);
            }
            //分页
            request.source()
                    .from((itemPageQuery.getPage()-1)*itemPageQuery.getSize())
                    .size(itemPageQuery.getSize());
            //高亮
            request.source().highlighter(SearchSourceBuilder.highlight()
                    .field("key").preTags("<em>").postTags("<em>"));
            //发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //解析结果
            return handleResponse(response);
        } catch (IOException e) {
            log.info("搜索失败");
        }
        return null;
    }
    //基本搜索参数
    private BoolQueryBuilder boolSearch(ItemPageQuery itemPageQuery) {
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        //key
        String key = itemPageQuery.getKey();
        if (!StringUtils.isEmpty(key)){
            bool.must(QueryBuilders.matchQuery("name",key));
        }else {
            bool.must(QueryBuilders.matchAllQuery());
        }
        //brand
        String brand = itemPageQuery.getBrand();
        if (!StringUtils.isEmpty(brand)){
            bool.must(QueryBuilders.matchQuery("brand",brand));
        }
        //category
        String category = itemPageQuery.getCategory();
        if (!StringUtils.isEmpty(category)){
            bool.must(QueryBuilders.matchQuery("category",category));
        }
        //price
        Integer minPrice = itemPageQuery.getMinPrice();
        Integer maxPrice = itemPageQuery.getMaxPrice();
        if ((!StringUtils.isEmpty(minPrice)) && (!StringUtils.isEmpty(minPrice))){
            bool.filter(QueryBuilders.rangeQuery("price").gte(minPrice).lte(maxPrice));
        }
        return bool;
    }
    //解析结果
    private PageDTO<ItemDoc> handleResponse(SearchResponse response) {
        PageDTO<ItemDoc> pageDTO = new PageDTO<>();
        ArrayList<ItemDoc> list = new ArrayList<>();

        SearchHits hits = response.getHits();

        //获取总条数
        long total = hits.getTotalHits().value;
        pageDTO.setTotal(total);
        System.out.println("共搜索到"+total+"条数据");

        //遍历结果数组
        SearchHit[] hitsArr = hits.getHits();
        for (SearchHit hit : hitsArr) {
            //得到_source,原始json文档
            String source = hit.getSourceAsString();
            //反序列化并打印
            ItemDoc itemDoc = JSONUtil.toBean(source, ItemDoc.class);
            list.add(itemDoc);
            System.out.println(itemDoc);
        }
        pageDTO.setList(list);
        return pageDTO;
    }

    /**
     * 自动补全词条
     * @param key
     * @return
     */
    @Override
    public List<String> suggestion(String key) {


        return null;
    }

    @Autowired
    ItemClient itemClient;
    /**
     * 删除下架商品
     * @param id
     */
    @Override
    public void deleteStatus(Long id) {
        //删除请求
        DeleteRequest deleteRequest = new DeleteRequest();
        //参数
        deleteRequest.index("hmall").id(id.toString());
        //发送删除请求
        try {
            client.delete(deleteRequest,RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.info("删除下架商品失败");
            throw new RuntimeException();
        }
    }
    /**
     * 新增上架商品
     * @param id
     */
    @Override
    public void saveStatus(Long id) {
        try {
            //根据id查询商品
            ItemDTO item = itemClient.getItemById(id);
            ItemDoc itemDoc = new ItemDoc();
            BeanUtils.copyProperties(item,itemDoc);
            //新增请求
            IndexRequest indexRequest = new IndexRequest();
            indexRequest.index("hmall").id(id.toString());
            //新增参数
            String itemDocJson = new ObjectMapper().writeValueAsString(itemDoc);
            indexRequest.source(itemDocJson, XContentType.JSON);
            //发送请求
            client.index(indexRequest,RequestOptions.DEFAULT);
        } catch (Exception e) {
            log.info("新增上架商品失败");
            throw new RuntimeException();
        }
    }
}
